package com.warmheart.impl.sys;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.hutool.core.date.DateUtil;

import com.warmheart.base.config.WhTransactionalControl;
import com.warmheart.base.service.impl.BaseService;
import com.warmheart.core.ex.BusinessException;
import com.warmheart.dao.sys.SysSequenceDao;
import com.warmheart.entity.sys.SysSequence;
import com.warmheart.service.sys.ISysSequenceService;

/**
 * 
 * @ClassName: SysSequenceService
 * @Description: 序号Service，对应表名称为tb_sys_sequence
 *               温馨提示：对外提供的接口，原则上这里只写自定义方法
 * @author ZhangJianyang
 * @date 2025-06-16 09:37:02
 *
 */
@Service(value = "sysSequenceService")
public class SysSequenceService extends BaseService<SysSequence> implements ISysSequenceService {

    @Autowired
    private SysSequenceDao sysSequenceDao;

    @Override
    public SysSequenceDao getDao() {
        return this.sysSequenceDao;
    }

    /**
     * 
     * @Title: increase
     * @Description: 获取流水号，并自增
     * @author ZhangJianyang
     * @param seqType
     * @return
     * @throws Exception
     */
    @Override
    @WhTransactionalControl
    public String increase(String seqType) throws Exception {
        SysSequence sequence = new SysSequence();
        sequence.setSeqType(seqType);
        sequence = sysSequenceDao.selectOneCustom(sequence, "selectOneForUpdate");
        if (null == sequence) {
            throw new BusinessException("无效的流水号类型");
        }

        BigInteger serialNumber;
        if (sequence.getIsDateUpdate() && !DateUtil.isSameDay(sequence.getCstModify(), DateUtil.date())) {
            SysSequence sequenceCheck = new SysSequence();
            sequenceCheck.setId(sequence.getId());
            sequenceCheck.setSerialNumber(BigInteger.valueOf(2));
            sequenceCheck.setCstModify(DateUtil.date());
            sysSequenceDao.updateBySelective(sequenceCheck);
            serialNumber = BigInteger.ONE;
            return generateSerialNum(sequence, serialNumber);
        }

        SysSequence sequenceCheck = new SysSequence();
        sequenceCheck.setId(sequence.getId());
        sequenceCheck.setSerialNumber(sequence.getSerialNumber().add(BigInteger.valueOf(1)));
        sysSequenceDao.updateBySelective(sequenceCheck);
        serialNumber = sequence.getSerialNumber();
        return generateSerialNum(sequence, serialNumber);
    }

    /**
     * 
     * @Title: increase
     * @Description: 获取指定数量的流水号
     * @author ZhangJianyang
     * @param seqType
     * @param count
     * @return
     * @throws Exception
     */
    @Override
    @WhTransactionalControl
    public List<String> increase(String seqType, Integer count) throws Exception {
        SysSequence sequence = new SysSequence();
        sequence.setSeqType(seqType);
        sequence = sysSequenceDao.selectOneCustom(sequence, "selectOneForUpdate");
        if (null == sequence) {
            throw new BusinessException("无效的流水号类型");
        }

        BigInteger serialNumber;
        List<String> serialNums = new ArrayList<>();
        if (sequence.getIsDateUpdate() && !DateUtil.isSameDay(sequence.getCstModify(), DateUtil.date())) {
            SysSequence sequenceCheck = new SysSequence();
            sequenceCheck.setId(sequence.getId());
            sequenceCheck.setSerialNumber(BigInteger.valueOf(count + 1));
            sequenceCheck.setCstModify(DateUtil.date());
            sysSequenceDao.updateBySelective(sequenceCheck);
            serialNumber = BigInteger.ONE;
        } else {
            // 递增
            SysSequence sequenceCheck = new SysSequence();
            sequenceCheck.setId(sequence.getId());
            sequenceCheck.setSerialNumber(sequence.getSerialNumber().add(BigInteger.valueOf(count)));
            sysSequenceDao.updateBySelective(sequenceCheck);
            serialNumber = sequence.getSerialNumber();
        }

        for (int i = 0; i < count; i++) {
            serialNums.add(generateSerialNum(sequence, serialNumber.add(BigInteger.valueOf(i))));
        }
        return serialNums;
    }

    private String generateSerialNum(SysSequence sequence, BigInteger serialNumber) {
        if (sequence.getDateRule() != null && !sequence.getDateRule().trim().isEmpty()) {
            return sequence.getPrefix() + DateUtil.format(DateUtil.date(), sequence.getDateRule())
                    + padZerosPrefix(serialNumber, sequence.getSerialLength());
        }

        return sequence.getPrefix() + padZerosPrefix(serialNumber, sequence.getSerialLength());
    }

    private String padZerosPrefix(BigInteger number, Integer len) {
        return String.format("%0" + len + "d", number);
    }

}
